
MaxModLoader.Create(MaxMod_Loader_Wav,"Microsoft Wave ~q.wav~q","wav")


Function MaxMod_Loader_wav:TMusic(File:Object)
	Return TWavStream.Load(File)
EndFunction

Private

Function ReadTag$( stream:TStream )
	Local tag:Byte[4]
	If stream.ReadBytes( tag,4 )<>4 Return Null
	Return Chr(tag[0])+Chr(tag[1])+Chr(tag[2])+Chr(tag[3])
End Function

Public


Rem
bbdoc: Provides WAV format streaming. 
End Rem
Type TWavStream Extends TMusic

	Field stream:TStream
	Field samples:Int		
	Field size:Int				' in bytes
	Field loopseek:Int
	
	Function Load:TWavStream(File:Object)
	
		Local stream:TStream=LittleEndianStream(OpenFile(file,1,0))
		
		If ReadTag( stream )<>"RIFF" Return Null
		Local w_len:Int=stream.ReadInt()-8
		If ReadTag( stream )<>"WAVE" Return Null
		If ReadTag( stream )<>"fmt " Return Null
		
		Local w_len2:Int=stream.ReadInt()
		Local w_comp:Int=stream.ReadShort()
		If w_comp<>1 Return Null
		
		Local w_chans:Int		= stream.ReadShort()
		Local w_hz:Int			= stream.ReadInt()
		Local w_bytespersec:Int	= stream.ReadInt()
		Local w_pad:Int			= stream.ReadShort()
		Local w_bits:Int		= stream.ReadShort()
		
		Local format:Int
		Select True
			Case w_bits=8 And w_chans=1		; format=MM_MONO8
			Case w_bits=8 And w_chans=2		; format=MM_STEREO8
			Case w_bits=16 And w_chans=1	; format=MM_MONO16
			Case w_bits=16 And w_chans=2	; format=MM_STEREO16
		Default Return Null
		End Select

		If w_len2>16 stream.SkipBytes( w_len2-16 )
		
		Local loopseek:Int = StreamPos(Stream)
		
		Local size:Int
		While Not stream.Eof()

			Local tag$=Readtag( stream )
			If tag<>"data"
				Local sz:Int=stream.ReadInt()
				stream.SkipBytes( sz )
				Continue
			EndIf

			size = stream.ReadInt()
			Exit
			
		Wend
		
		Local This:TWavStream = New TWavStream
		This.Stream 		= Stream
'		This.samples 		= Samples
		This.Sample_Rate 	= w_hz
		This.Stream_Size	= size
		This.STREAM_FORMAT  = format
		This.LoopSeek 		= LoopSeek

		Return This
		
	EndFunction

	Method Free()
	EndMethod
 
	Method Stop()
		'Super.Stop
		Stream.Seek(LoopSeek); Stream_Pos=LoopSeek
	EndMethod

	Method FillBuffer(SoundData:Int,Length:Int)

		If Length=0 Return

		If Stream_Pos+Length < Stream_Size
			stream.ReadBytes(Short Ptr(SoundData),Length)
			Stream_Pos:+Length
		Else
			Local n:Int,remainder:Int = Stream_Size-Stream_Pos
			stream.ReadBytes(Byte Ptr(SoundData),remainder)
			If Stream_Loop = True
				Stream.Seek(LoopSeek); Stream_Pos=LoopSeek
			Else
				PlayStatus = False
				Stop
			EndIf
		EndIf
		
	EndMethod
	

EndType
